/**
 * @file flash.c
 * @author ait_zhengchunyu (ait_zhengchunyu@163.com)
 * @brief  主要抽象flash 相关操作。存储相关信息
 * @version 0.1
 * @date 2022-02-09
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include "./flash.h"
#include "../dbg/dbg.h"

static uint8_t flash_buf[1024] = {0};
static struct flash_dev_t flash_device;

static int flash_write_byte (struct flash_dev_t *dev,uint16_t num,uint8_t  val)
{
    if (dev==NULL)
    {
        //dbg_error("flash flash_write_byte dev is NULL\r\n");
        return -1;
    }
    if(num>=dev->size){
        //dbg_error("flash flash_write_byte num is greater than flash size: %d\r\n",dev->size);
    }
    dev->cache[num] = val;
    dev->refresh(dev);
    return 0;
}
static int flash_read_byte  (struct flash_dev_t *dev,uint16_t num,uint8_t* val)
{
    if (dev==NULL)
    {
        //dbg_error("flash flash_read_byte dev is NULL\r\n");
        return -1;
    }
    if(num>=dev->size){
        //dbg_error("flash flash_read_byte num is greater than flash size: %d\r\n",dev->size);
        return -2;
    }
    *val = dev->cache[num];
    return 0;
}

/**
 * @brief 写入flash buf 大小为页大小
 * 
 * @param dev       flash 句柄
 * @param page      页编号 从0 开始
 * @param pwbuf     写入首地址
 * @param size      写入长度
 * @return int 
 */
int flash_write_page(struct flash_dev_t *dev,uint8_t page,uint8_t *pwbuf,uint16_t size)
{
    int i = 0;
    uint16_t tmp = 0;
    if (dev==NULL)
    {
        //dbg_error("flash flash_write_page dev is NULL\r\n");
        return -1;
    }
    if(page>=dev->page_num){
        //dbg_error("flash flash_write_page num is greater than flash size: %d\r\n",dev->page_num);
        return -2;
    }
    if(size>FLASH_PAGE_SIZE)tmp = FLASH_PAGE_SIZE;
    else tmp = size;
    for ( i = 0; i < tmp; i++)
    {
        dev->cache[page*FLASH_PAGE_SIZE+i] = pwbuf[i];
    }
    dev->refresh(dev);
    return 0;
}
/**
 * @brief 读取flash整页数据
 * 
 * @param dev 
 * @param page 
 * @param prbuf 
 * @param size 
 * @return int 
 */
int flash_read_page(struct flash_dev_t *dev,uint8_t page,uint8_t *prbuf,uint16_t size)
{
    int i = 0;
    uint16_t tmp = 0;
    if(dev==NULL)
    {
        //dbg_error("flash_read_page dev is NULL \r\n");
        return -1;
    }
    if(page >=dev->page_num)
    {
        //dbg_error("flash_read_page page out of range  dev max page is %d \r\n",dev->page_num);
        return -2;
    }
    if(size >= FLASH_PAGE_SIZE)
    {
        tmp =FLASH_PAGE_SIZE;
    }
    else
    {
        tmp = size;
    }
    for(i = 0; i < tmp; i++)
    {
        prbuf[i] = dev->cache[page*FLASH_PAGE_SIZE+1];
    }
    return 0;
}
/**
 * @brief 读取flash 数组中数据
 * 
 * @param dev       
 * @param start_num 起始位置
 * @param prbuf      读取数组
 * @param len       读取长度
 * @return int 
 */
static int flash_read_array(struct flash_dev_t *dev,uint16_t start_num,uint8_t* prbuf,uint8_t len)
{
    int i;

    if(dev==NULL)
    {
        //dbg_error("flash_read_array dev is NULL \r\n");
        return -1;
    }
    if((start_num >=dev->size)||((start_num+len) >= dev->size))
    {
        //dbg_error("flash_read_array page out of range  dev max page is %d \r\n",dev->size);
        return -2;
    }
    for(i=0;i<len;i++)
    {
        prbuf[i] = dev->cache[start_num+i];
    }
    return 0;
}
/**
 * @brief 向flash 写入指定长度的数组
 * 
 * @param dev 
 * @param start_num   起始位置
 * @param pwbuf       数组首地址
 * @param len         数组长度
 * @return int 
 */
static int flash_write_array(struct flash_dev_t *dev,uint16_t start_num,uint8_t* pwbuf,uint8_t len)
{
    int i;
    if(dev==NULL)
    {
        //dbg_error("flash_write_array dev is NULL \r\n");
        return -1;
    }
    if((start_num >=dev->size)||((start_num+len) >= dev->size))
    {
        //dbg_error("flash_write_array page out of range  dev max page is %d \r\n",dev->size);
        return -2;
    }
    for (i = 0; i < len; i++)
    {
        dev->cache[start_num+i]=pwbuf[i];
    }
    dev->refresh(dev);
    return 0;
}
/**
 * @brief 刷新flash 整体写入flash
 * 
 * @param dev 
 * @return int 
 */
static int flash_refresh(struct flash_dev_t *dev)
{
    /**
     * @brief 需要hal层提供
     * 
     */
    flash_hal_write_allpage(dev->cache,FLASH_PAGE_SIZE);
		return 0;
}
/**
 * @brief 读取flash全部数据
 * 
 * @param dev 
 * @return int 
 */
static int flash_read_allpage(struct flash_dev_t *dev)
{
    //需要hal层提供
    flash_hal_read_all(flash_buf,FLASH_PAGE_SIZE);
	return 0;
}
static int flash_check_magic (struct flash_dev_t *dev)
{
     dev->read_allpage(dev);
     if(dev->cache[0] ==FLASH_MAGIC_VALUE)
     {
         return FLASH_MAGIC_VALUE;
     }
     else 
     {
         return 0;
     }
}

int flash_init(struct flash_dev_t **dev)
{

    flash_device.page_num       = FLASH_PAGE_NUM;
    flash_device.page_size      = FLASH_PAGE_SIZE;
    flash_device.size           = flash_device.page_num*flash_device.page_size;
    flash_device.write_byte     = flash_write_byte;
    flash_device.read_byte      = flash_read_byte;
    flash_device.write_page     = flash_write_page;
    flash_device.read_page      = flash_read_page;
    flash_device.read_array     = flash_read_array;
    flash_device.write_array    = flash_write_array;
    flash_device.read_allpage   = flash_read_allpage;
    flash_device.write_allpage  = flash_refresh;
    flash_device.refresh        = flash_refresh; 
    flash_device.check_magic    = flash_check_magic;
		flash_device.cache = flash_buf;
    *dev = &flash_device;

    return 0;
}


